package com.moon.java.code.analyzer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.alibaba.fastjson2.JSON;

public class DubboClientXMLParser {
    private static final Logger LOGGER = Logger.getLogger(DubboClientXMLParser.class.getName());

    // 解析单个 XML 文件的方法
    public static Set<String> parseFile(File file) {
        Set<String> clientSet = new HashSet<>();
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(file);

            NodeList resultMapNodes = doc.getElementsByTagName("dubbo:reference");
            for (int i = 0; i < resultMapNodes.getLength(); i++) {
                Element resultMapElement = (Element) resultMapNodes.item(i);
                clientSet.add(resultMapElement.getAttribute("interface"));
            }

        } catch (ParserConfigurationException | SAXException | IOException e) {
            LOGGER.log(Level.SEVERE, "Error parsing XML file: " + file.getName(), e);
        }
        return clientSet;
    }

    // 递归迭代目录，查找所有 XML 文件并解析
    private static Set<String> iterateDirectory(File directory) {
        Set<String> mapperInfoMap = new HashSet<>();
        if (directory.exists() && directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        mapperInfoMap.addAll(iterateDirectory(file));
                    } else if (file.getName().endsWith(".xml")) {
                        Set<String> mapperInfo = parseFile(file);
                        mapperInfoMap.addAll(mapperInfo);
                    }
                }
            }
        }
        return mapperInfoMap;
    }

    // 解析目录，先检查序列化文件，不存在则解析并序列化
    @SuppressWarnings("unchecked")
    public static Set<String> parseDirectory(String directoryPath, boolean useCache) {
        File directory = new File(directoryPath);
        String lastDirectoryName = directory.getName();
        File serFile = new File(lastDirectoryName + ".ser");
        Set<String> mapperInfoMap = null;

        if (useCache && serFile.exists()) {
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(serFile))) {
                mapperInfoMap = (Set<String>) ois.readObject();
            } catch (IOException | ClassNotFoundException e) {
                LOGGER.log(Level.SEVERE, "Error reading serialized file: " + serFile.getName(), e);
            }
        }

        if (mapperInfoMap == null) {
            mapperInfoMap = iterateDirectory(directory);
            try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(serFile))) {
                oos.writeObject(mapperInfoMap);
            } catch (IOException e) {
                LOGGER.log(Level.SEVERE, "Error writing serialized file: " + serFile.getName(), e);
            }
        }
        return mapperInfoMap;
    }

    public static void main(String[] args) {
        String directoryPath = "D:\\git\\ecej-pay-task\\src\\main\\resources\\dubbo";
        boolean useCache = true; // 可以根据需要修改该值
        Set<String> mapperInfoMap = parseDirectory(directoryPath, useCache);
        String jsonResult = JSON.toJSONString(mapperInfoMap);
        System.out.println(jsonResult);
    }
}
